package com.xayy.health.mgt.service.impl;

import cn.kawins.base.result.CheckResult;
import cn.kawins.base.utils.BeanUtil;
import cn.kawins.base.utils.CollUtil;
import cn.kawins.base.utils.annotation.DataTable;
import cn.kawins.mybatis.base.BaseServiceImpl;
import com.xayy.health.core.utils.ConvertUtils;
import com.xayy.health.core.utils.DoshellUtils;
import com.xayy.health.core.utils.FileInfosUtils;
import com.xayy.health.core.utils.GetPidUtil;
import com.xayy.health.mgt.mapper.HealthAlgorithmManageMapper;
import com.xayy.health.mgt.model.AlgorithmParams;
import com.xayy.health.mgt.model.HealthAlgorithmManage;
import com.xayy.health.mgt.model.dto.AlgorithmDto;
import com.xayy.health.mgt.model.vo.AlgorithmModelVo;
import com.xayy.health.mgt.service.AlgorithmParamService;
import com.xayy.health.mgt.service.HealthAlgorithmManageService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author zhangxa
 */
@Service
public class HealthAlgorithmManageServiceImpl extends BaseServiceImpl<HealthAlgorithmManage> implements HealthAlgorithmManageService {

    @Resource
    private HealthAlgorithmManageMapper healthAlgorithmManageMapper;

    @Autowired
    private AlgorithmParamService algorithmParamService;

    /**
     * 根据类型获取可用算法列表
     *
     * @param type 1:剔野,2:填充,3:平滑,4:事后诊断,5:趋势预测
     * @return 算法列表信息
     */
    @Override
    public List<HealthAlgorithmManage> getAlgorithmByType(Integer type) {
        HealthAlgorithmManage build = HealthAlgorithmManage.builder().algorithmType(type).build();
        List<HealthAlgorithmManage> select = select(build);
        return select.stream().sorted(Comparator.comparing(HealthAlgorithmManage::getCreateTime).reversed()).collect(Collectors.toList());
    }

    /**
     * 算法状态上报
     *
     * @return 结果日志
     */
    @Override
    public List<HealthAlgorithmManage> selectAlgorithmByType() {
        return healthAlgorithmManageMapper.selectAlgorithmByType();
    }

    /**
     * 保存上传算法信息
     *
     * @param algorithmDto 算法信息
     */
    @Override
    public void saveUploadMessage(AlgorithmDto algorithmDto) {
        HealthAlgorithmManage healthAlgorithmManage =
                ConvertUtils.sourceToTarget(algorithmDto, HealthAlgorithmManage.class);
        insert(healthAlgorithmManage);
    }

    /**
     * 新增算法信息
     *
     * @param healthAlgorithmManage 算法信息
     * @param algorithmFile         算法文件
     * @return 结果日志
     */
    @Override
    public CheckResult<?> saveAlgorithmInfo(HealthAlgorithmManage healthAlgorithmManage, MultipartFile algorithmFile) {
        // 上传文件
        if (BeanUtil.isEmpty(algorithmFile)) {
            return CheckResult.fail("算法文件不能为空");
        }
        String filePath = null;
        try {
            if (algorithmFile.getOriginalFilename().endsWith("zip"))
                filePath = FileInfosUtils.uploadZip(algorithmFile);
            else
                filePath = FileInfosUtils.uploadFile(algorithmFile);
        } catch (Exception e) {
            return CheckResult.fail(e.getMessage());
        }
        // 校验code和和name是否重复
        List<HealthAlgorithmManage> selectCode =
                select(HealthAlgorithmManage.builder().algorithmCode(healthAlgorithmManage.getAlgorithmCode()).build());
        if (CollUtil.isNotEmpty(selectCode)) {
            return CheckResult.fail("算法code:" + healthAlgorithmManage.getAlgorithmCode() + "已存在");
        }
        List<HealthAlgorithmManage> selectName =
                select(HealthAlgorithmManage.builder().algorithmName(healthAlgorithmManage.getAlgorithmName()).build());
        if (CollUtil.isNotEmpty(selectName)) {
            return CheckResult.fail("算法名称:" + healthAlgorithmManage.getAlgorithmName() + "已存在");
        }
        healthAlgorithmManage.setId(null);
        healthAlgorithmManage.setCreateTime(new Date());
        healthAlgorithmManage.setAlgorithmPath(filePath);
        healthAlgorithmManage.setTrialAddr(healthAlgorithmManage.getTrialAddr());
        healthAlgorithmManage.setPredictAddr(healthAlgorithmManage.getPredictAddr());
        healthAlgorithmManage.setServerState(false);
        String algorithmFileName = Objects.requireNonNull(algorithmFile.getOriginalFilename()).replace(".py", "");
        healthAlgorithmManage.setAlgorithmFileName(algorithmFileName);
        if (algorithmFile.getOriginalFilename().endsWith("zip"))
            healthAlgorithmManage.setStartServiceFile(healthAlgorithmManage.getStartServiceFile());
        insert(healthAlgorithmManage);
        return CheckResult.success("算法新建成功");
    }

    /**
     * 启动算法服务
     * @param healthAlgorithmManage 算法信息
     * @return 结果日志
     */
    @Override
    public CheckResult<?> startAlgorithmServer(HealthAlgorithmManage healthAlgorithmManage){
        List<String> paramlist = new ArrayList<>();
        paramlist.add(healthAlgorithmManage.getAlgorithmPath() + "/" + healthAlgorithmManage.getStartServiceFile());
        DoshellUtils.onCall("python",paramlist);
        healthAlgorithmManage.setServerState(true);
        updateByIdSelective(healthAlgorithmManage);
        return CheckResult.success("算法服务启动");
    }

    /**
     * 停止算法服务
     * @param healthAlgorithmManage 算法实体
     * @return 结果日志
     */
    @Override
    public CheckResult<?> stopAlgorithmServer(HealthAlgorithmManage healthAlgorithmManage){
        String closeResult = "";
        try {
            closeResult = GetPidUtil.stopByPid(healthAlgorithmManage.getAlgorithmPath() + "/" + healthAlgorithmManage.getStartServiceFile());
            healthAlgorithmManage.setServerState(false);
            updateByIdSelective(healthAlgorithmManage);
        }catch (Exception e){
            e.printStackTrace();
        }
        log.info("算法服务停止,"+closeResult);
        return CheckResult.success("算法服务停止,"+closeResult);
    }

    /**
     * 获取算法信息
     *
     * @param paramMap 入参
     * @return List<HealthAlgorithmManage>
     */
    @DataTable("algorithmInfoPageList")
    public List<HealthAlgorithmManage> getAlgorithmInfo(Map<String, Object> paramMap) {
        return selectAll();
    }

    /**
     * 查询模型信息
     *
     * @param id 信息
     * @return 结果日志
     */
    @Override
    public CheckResult<?> selectModel(Long id) {
        HealthAlgorithmManage healthAlgorithmManage = selectById(id);

        List<AlgorithmParams> algorithmParams = algorithmParamService.select(AlgorithmParams.builder().algorithmName(healthAlgorithmManage.getAlgorithmName()).build());
        AlgorithmModelVo algorithmModelVo = BeanUtil.copyProperties(healthAlgorithmManage, AlgorithmModelVo.class);
        algorithmModelVo.setAlgorithmParams(algorithmParams);
        return CheckResult.success(algorithmModelVo);
    }

}
